package com.grt.condify.reflect;


import com.grt.condify.utils.StringUtil;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Class和其对应字段的缓存类，该类和Class2MethodInNonStaticCache类似，
 * 不过考虑到Annotation的普遍使用，该类会提供Field到Annotation的映射，方便更快速的获得Annotation信息
 * <p>
 * Created by cy on 16/5/26.
 */
public class Class2FieldInNonStaticCache extends Class2MapInNonStaticCache<String, Field, List<Annotation>> {

    public static final Field[] EMPTY_FIELDS = new Field[0];

    public static final List<Annotation> EMPTY_ANNOTATION = new ArrayList<>();

    @Override
    public boolean isKeyEmpty(String key) {
        return StringUtil.isEmpty(key);
    }

    @Override
    public boolean isKeyOfMapEmpty(Field keyOfMap) {
        return keyOfMap == null;
    }

    @Override
    public boolean isValueIsEmpty(List<Annotation> value) {
        return value == null || value.size() == 0;
    }

    /**
     * 获得指定class下的所有字段
     * 如果指定的{@code className}不存在,则返回长度为0的Field数组
     *
     * @param className 类名
     * @return 属性结合
     */
    public Field[] getFields(String className) {
        final Map<Field, List<Annotation>> fieldAnnotationMap = mapOfFieldAndAnnotation(className);
        return fieldAnnotationMap == null || fieldAnnotationMap.size() == 0 ? EMPTY_FIELDS : fieldAnnotationMap.keySet().toArray(new Field[fieldAnnotationMap.size()]);
    }

    /**
     * 得到指定class的Field及其Annotation的映射关系
     * 如果指定的{@code className}不存在,则返回null
     *
     * @param className 类名
     */
    public Map<Field, List<Annotation>> mapOfFieldAndAnnotation(String className) {
        if (isKeyEmpty(className) || !isContain(className)) {
            return null;
        }
        return firstLevelCaches.get(className).size() == 0 ? null : firstLevelCaches.get(className);
    }

    /**
     * 得到指定Field的Annotation
     * 如果指定的{@code className}不存在,则返回null, 如果指定的{@code field}没有Annotation,则返回长度为0的Annotation列表
     *
     */
    public List<Annotation> getAnnotationOf(String className, Field field) {
        final Map<Field, List<Annotation>> fieldAnnotationMap = mapOfFieldAndAnnotation(className);
        if (fieldAnnotationMap == null || fieldAnnotationMap.size() == 0) {
            return null;
        }
        final List<Annotation> annotations = fieldAnnotationMap.get(field);
        return annotations == null || annotations.size() == 0 ? EMPTY_ANNOTATION : annotations;
    }
}
